home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1994 January / PSL Monthly Shareware CD-ROM (Public Software Library) (January 1994).iso / games / dos / board / backgam.com / MOVEGEN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1979-11-30  |  21.8 KB  |  931 lines

  1. /*P*/
  2. /****************************************************************/
  3. /*                                */
  4. /* movegen - these routines generate all possible moves for    */
  5. /* each color. They are not at all trivial, and you'd think    */
  6. /* that they are too long for one function. However, breaking    */
  7. /* these apart makes them run more slowly, and makes them much    */
  8. /* more difficult to follow, unfortunately.            */
  9. /*                                */
  10. /****************************************************************/
  11.  
  12. #include    <stdio.h>
  13. #include    "bkg.h"
  14.  
  15. #define        WORST        -32768
  16. #define        TEXT_COLOR    0x07
  17. #define        MIN( a, b )    ( a < b ? a : b )
  18. #define        OFF        0
  19. #define        ON        1
  20.  
  21. /*P*/
  22. /****************************************************************/
  23. /*                                */
  24. /* b_movegen                            */
  25. /*                                */
  26. /* This will generate all of the possible moves for black. If    */
  27. /* the "computer" parameter is false, this procedure will look    */
  28. /* to find the moves that are possible for black, returning the    */
  29. /* number. This is so that the black player is required to    */
  30. /* make 2 moves if a 2-move is possible. If the "computer" flag    */
  31. /* is true, the routine calls "b_eval" to find the best of the    */
  32. /* moves generated. This best move is formatted and returned in    */
  33. /* "line", in a format that can be understood by the command    */
  34. /* parser (just as if a user had entered it).            */
  35. /*                                */
  36. /* An explanation of the "level" variable is in order. It'll    */
  37. /* keep temporary tabs on how many dice we have been able to    */
  38. /* apply in a given attempt. If we find a possible move that    */
  39. /* has a value in "level" that is < the largest possible    */
  40. /* "level" so far, then this is illegal, since we have to use    */
  41. /* all of the dice if we can.                    */
  42. /*                                */
  43. /****************************************************************/
  44.  
  45. b_movegen( die_1, die_2, computer, biggest, line, echo )
  46.  
  47. int    die_1, die_2;
  48. int    computer, *biggest;
  49. char    line[];
  50. int    echo;
  51.  
  52.     {
  53.  
  54.     char    *format[ 5 ];
  55.     int    p[ 4 ], die[ 4 ], best_p[ 4 ], best_die[ 4 ], i, j;
  56.     int    temp, level, finished, copy, best, value, count;
  57.     int    test[ SIZE ][ 3 ];
  58.  
  59.     /* These are format spec's to be used    */
  60.     /* by computer generated moves.        */
  61.  
  62.     if ( ! computer )
  63.         *biggest = 0;
  64.     else
  65.         {
  66.         format[ 0 ] = "software bug?";
  67.         format[ 1 ] = "%d/%d";
  68.         format[ 2 ] = "%d/%d %d/%d";
  69.         format[ 3 ] = "%d/%d %d/%d %d/%d";
  70.         format[ 4 ] = "%d/%d %d/%d %d/%d %d/%d";
  71.         best = WORST;
  72.         }
  73.  
  74.     count = 0;
  75.     die[ 0 ] = die[ 2 ] = die_1;
  76.     die[ 1 ] = die[ 3 ] = die_2;
  77.  
  78.     /* Copy the board into the test area. The 2    */
  79.     /* is a temp. holding area for the opponents    */
  80.     /* men that are bumped off.            */
  81.  
  82.     movmem( board, test, BOARD_IN_BYTES );
  83.  
  84.     finished = 0;
  85.  
  86.     while ( finished < 2 )
  87.         {
  88.  
  89.         /* Try all possible first uses for the    */
  90.         /* dice, from the bar on out.        */
  91.  
  92.         for( p[ 0 ] = B_BAR; p[ 0 ] < 25; p[ 0 ]++ )
  93.             {
  94.  
  95.              /* If this is an illegal move, forgetit */
  96.  
  97.             if ( ! b_valid_move( test, p[ 0 ], die[ 0 ] ) )
  98.                 continue;
  99.  
  100.             level = 1;
  101.  
  102.             b_change( test, p[ 0 ], die[ 0 ], OFF );
  103.  
  104.             /* Now do the same thing within here,    */
  105.             /* using the other die as the value.    */
  106.     
  107.             for( p[ 1 ] = B_BAR; p[ 1 ] < 25; p[ 1 ]++ )
  108.                 {
  109.     
  110.                 if ( ! b_valid_move( test, p[ 1 ], die[ 1 ] ) )
  111.                     continue;
  112.     
  113.                 b_change( test, p[ 1 ], die[ 1 ], OFF );
  114.  
  115.                 /* If we have doubles, we have yet another    */
  116.                 /* iteration of the two dice to go through here    */
  117.     
  118.                 if ( die[ 0 ] == die[ 1 ] )
  119.                     {
  120.     
  121.                     for( p[ 2 ] = B_BAR; p[ 2 ] < 25; p[ 2 ]++ )
  122.                         {
  123.  
  124.                         if ( ! b_valid_move( test, p[ 2 ], die[ 2 ] ) )
  125.                             continue;
  126.     
  127.                         level = 3;
  128.     
  129.                         b_change( test, p[ 2 ], die[ 2 ], OFF );
  130.  
  131.                         /* Now do the same thing within here,    */
  132.                         /* using the other die as the value.    */
  133.     
  134.                         for( p[ 3 ] = B_BAR; p[ 3 ] < 25; p[ 3 ]++ )
  135.                             {
  136.     
  137.                             if ( ! b_valid_move( test, p[ 3 ], die[ 3 ] ) )
  138.                                 continue;
  139.  
  140.                             b_change( test, p[ 3 ], die[ 3 ], OFF );
  141.     
  142.                             if ( bar_first( p, MIN( board[ B_BAR ][ BLACK ], 4 ) ) )
  143.                                 {
  144.  
  145.                                 level = 4;÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷÷ loop */
  146.     
  147.                         if ( level == 3 )
  148.                             {
  149.  
  150.                             if ( ( *biggest <= 3                     ) &&
  151.                                  ( bar_first( p, MIN( board[ B_BAR ][ BLACK ], 3 ) ) ) )
  152.                                 {
  153.  
  154.                                 if ( ! computer )
  155.                                     *biggest = ( *biggest < 3 ) ? 3 : *biggest;
  156.                                 else
  157.                                     {
  158.  
  159.                                     value = b_eval( test, count++ );
  160.                                     if ( value > best )
  161.                                         {
  162.  
  163.                                         best = value;
  164.                                         for( copy = 0; copy < 3; copy++ )
  165.                                             {
  166.                                             best_p[ copy ] = p[ copy ];
  167.                                             best_die[ copy ] = die[ copy ];
  168.                                             }
  169.                                         }
  170.                                     }
  171.                                 }
  172.  
  173.                             } /* level 3 */
  174.     
  175.                         /* Put the pieces back where they were    */
  176.                         /* so that the next time through the    */
  177.                         /* loop we'll be using the originals.    */
  178.     
  179.                         b_change( test, p[ 2 ], die[ 2 ], ON );
  180.  
  181.                         } /* p[ 2 ] control loop */
  182.  
  183.                     /* If we had doubles but can only make    */
  184.                     /* two moves out of the possible 4...    */
  185.                     /* (Read the words "bug fix" here!)    */
  186.  
  187.                     if ( level == 1 )
  188.                         {
  189.  
  190.                         level = 2;
  191.  
  192.                         if ( ( *biggest <= 2                     ) &&
  193.                              ( bar_first( p, MIN( board[ B_BAR ][ BLACK ], 2 ) ) ) )
  194.                             {
  195.  
  196.                             if ( ! computer )
  197.                                 *biggest = ( *biggest < 2 ) ? 2 : *biggest;
  198.                             else
  199.                                 {
  200.  
  201.                                 value = b_eval( test, count++ );
  202.                                 if ( value > best )
  203.                                     {
  204.                                     best = value;
  205.                                     for( copy = 0; copy < 2; copy++ )
  206.                                         {
  207.                                         best_p[ copy ] = p[ copy ];
  208.                                         best_die[ copy ] = die[ copy ];
  209.                                         }
  210.                                     }
  211.                                 }
  212.                             }
  213.                         }
  214.  
  215.                     } /* Doubles handler */
  216.                 else
  217.                     {
  218.     
  219.                     /* If there were men on the original bar, we    */
  220.                     /* must remove them prior to making any other    */
  221.                     /* moves.                    */
  222.     
  223.                     if ( ( *biggest <= 2                     ) &&
  224.                          ( bar_first( p, MIN( board[ B_BAR ][ BLACK ], 2 ) ) ) )
  225.                         {
  226.  
  227.                         level = 2;
  228.  
  229.                         if ( ! computer )
  230.                             {
  231.                             *biggest = ( *biggest < 2 ) ? 2 : *biggest;
  232.                             return;
  233.                             }
  234.                         else
  235.                             {
  236.  
  237.                             value = b_eval( test, count++ );
  238.                             if ( value > best )
  239.                                 {
  240.  
  241.                                 best = value;
  242.                                 for( copy = 0; copy < 2; copy++ )
  243.                                     {
  244.                                     best_p[ copy ] = p[ copy ];
  245.                                     best_die[ copy ] = die[ copy ];
  246.                                     }
  247.                                 }
  248.                             }
  249.                         }
  250.     
  251.                     } /* not doubles */
  252.     
  253.                 b_change( test, p[ 1 ], die[ 1 ], ON );
  254.  
  255.                  } /* p[ 1 ] control loop */
  256.     
  257.             /* If "level" is still 1, we did not    */
  258.             /* find any use for the other die.    */
  259.     
  260.             if ( level == 1 )
  261.                 {
  262.  
  263.                 if ( ( *biggest <= 1                     ) &&
  264.                      ( bar_first( p, MIN( board[ B_BAR ][ BLACK ], 1 ) ) ) )
  265.                     {
  266.  
  267.                     if ( ! computer )
  268.                         *biggest = ( *biggest < 1 ) ? 1 : *biggest;
  269.                     else
  270.                         {
  271.  
  272.                         value = b_eval( test, count++ );
  273.                         if ( value > best )
  274.                             {
  275.                             best = value;
  276.                             best_p[ 0 ] = p[ 0 ];
  277.                             best_die[ 0 ] = die[ 0 ];
  278.                             }
  279.                         }
  280.                     }
  281.     
  282.                 } /* level 1 */
  283.     
  284.             /* Put the pieces back where they were    */
  285.             /* so that the next time through the    */
  286.             /* loop we'll be using the originals.    */
  287.     
  288.             b_change( test, p[ 0 ], die[ 0 ], ON );
  289.  
  290.             } /* p[ 0 ] control loop */
  291.  
  292.         /* If we had doubles, then we're done.    */
  293.         /* Otherwise rotate the dice (swap) and    */
  294.         /* do it all again, using, say 5,3 now    */
  295.         /* if the roll was 3,5.            */
  296.  
  297.         if ( die[ 0 ] == die[ 1 ] )
  298.             finished = 2;
  299.         else
  300.             {
  301.             temp = die[ 0 ];
  302.             die[ 0 ] = die[ 1 ];
  303.             die[ 1 ] = temp;
  304.             finished++;
  305.             }
  306.  
  307.         } /* while not finished yet */
  308.  
  309.     if ( computer )
  310.         {
  311.  
  312.         /* Format the move we've decided on.    */
  313.         /* The "eval" proc may have written    */
  314.         /* a few words below the dice, so we'll    */
  315.         /* space them out here.            */
  316.  
  317.         sprintf( line, format[ *biggest ],
  318.              best_p[ 0 ], best_die[ 0 ],
  319.              best_p[ 1 ], best_die[ 1 ],
  320.              best_p[ 2 ], best_die[ 2 ],
  321.              best_p[ 3 ], best_die[ 3 ] );
  322.  
  323.         write_at( 15, 65, "           ", TEXT_COLOR );
  324.  
  325.         } /* computer */
  326.  
  327.     } /* b_movegen */
  328.  
  329. /*P*/
  330. /****************************************************************/
  331. /*                                */
  332. /* b_exit_ok                            */
  333. /*                                */
  334. /* This returns true if it is ok for black to exit the board    */
  335. /* from this position, using this roll. "Test" is a temporary    */
  336. /* playing board.                        */
  337. /*                                */
  338. /****************************************************************/
  339.     
  340. b_exit_ok( test, psn, roll )
  341.  
  342. int    test[ SIZE ][ 3 ];
  343. int    psn, roll;
  344.  
  345.     {
  346.     
  347.     int    i;
  348.     
  349.     /* First off, if there is anyine not in the    */
  350.     /* inner table, you can not move them off.    */
  351.  
  352.     for( i = B_BAR; i < 19; i++ )
  353.         if ( test[ i ][ BLACK ] )
  354.             return( FALSE );
  355.  
  356.     /* Now, if the sum is EXACTLY 25, it is ok to    */
  357.     /* take them off regardless of the others.    */
  358.  
  359.     if ( ( psn + roll ) == B_HOME )
  360.         return( TRUE );
  361.  
  362.     /* Lastly, if we have, say, a 5 but there are    */
  363.     /* only men on 1, 2, and 3, ok to take off the    */
  364.     /* one at 3 only.                */
  365.  
  366.     for( i = psn - 1; i > 18; i-- )
  367.         if ( test[ i ][ BLACK ] )
  368.             return( FALSE );
  369.  
  370.     return( TRUE );
  371.  
  372.     } /* b_this_ok */
  373.  
  374. /*P*/
  375. /****************************************************************/
  376. /*                                */
  377. /* b_valid_move                            */
  378. /*                                */
  379. /* Return true if it is currently ok for black to move from    */
  380. /* the position "point" a distance of "die" on the board "test"    */
  381. /* Otherwise return false.                    */
  382. /*                                */
  383. /****************************************************************/
  384.  
  385. b_valid_move( test, point, die )
  386.  
  387. int    test[ SIZE ][ 3 ], point, die;
  388.  
  389.     {
  390.  
  391.     if ( ! test[ point ][ BLACK ] )
  392.         return( FALSE );
  393.  
  394.     if ( ( point + die ) > 24 )
  395.         {
  396.         if ( ! b_exit_ok( test, point, die ) )
  397.             return( FALSE );
  398.         }
  399.     else
  400.         {
  401.         if ( test[ point + die ][ WHITE ] >= 2 )
  402.             return( FALSE );
  403.         }
  404.  
  405.     return( TRUE );
  406.  
  407.     } /* b_valid_move */
  408.  
  409. /*P*/
  410. /****************************************************************/
  411. /*                                */
  412. /* b_change                            */
  413. /*                                */
  414. /* Take the "test" board and move the black player from the    */
  415. /* position "point" a distance of "die". We may either be     */
  416. /* putting the man on the new position from the old ("on" == 1)    */
  417. /* or we might be moving him back to where he was originally.    */
  418. /* The 2'th dimension on the most-significant dimension of     */
  419. /* "test" holds a 1 if a white player has been kicked off this    */
  420. /* spot.                            */
  421. /*                                */
  422. /****************************************************************/
  423.  
  424. b_change( test, point, die, on )
  425.  
  426. int    test[ SIZE ][ 3 ], point, die, on;
  427.  
  428.     {
  429.  
  430.     if ( on )
  431.         {
  432.  
  433.         test[ point ][ BLACK ]++;
  434.         if ( point + die <= 24 )
  435.             {
  436.             test[ point + die ][ BLACK ]--;
  437.             if ( test[ point + die ][ 2 ] )
  438.                 {
  439.                 test[ point + die ][ WHITE ]++;
  440.                 test[ point + die ][ 2 ]--;
  441.                 }
  442.             }
  443.         }
  444.     else
  445.         {
  446.  
  447.         test[ point ][ BLACK ]--;
  448.         if ( point + die <= 24 )
  449.             {
  450.             test[ point + die ][ BLACK ]++;
  451.             if ( test[ point + die ][ WHITE ] == 1 )
  452.                 {
  453.                 test[ point + die ][ WHITE ]--;
  454.                 test[ point + die ][ 2 ]++;
  455.                 }
  456.             }
  457.         }
  458.  
  459.     } /* b_change */
  460.  
  461. /*P*/
  462. /****************************************************************/
  463. /*                                */
  464. /* bar_first                            */
  465. /*                                */
  466. /* If there are men on the bar, then we must move them offa    */
  467. /* there before doing anything else. It's illegal not to.    */
  468. /*                                */
  469. /****************************************************************/
  470.  
  471. bar_first( points, num )
  472.  
  473. int    points[], num;
  474.  
  475.     {
  476.  
  477.     while( num )
  478.         if ( ( points[ num - 1 ] != 0  ) &&
  479.              ( points[ num - 1 ] != 25 ) )
  480.             return( FALSE );
  481.         else
  482.             num--;
  483.  
  484.     return( TRUE );
  485.  
  486.     } /* bar_first */
  487.  
  488. /*P*/
  489. /****************************************************************/
  490. /*                                */
  491. /* w_movegen                            */
  492. /*                                */
  493. /* This will generate all of the possible moves for white. If    */
  494. /* the "computer" parameter is false, this procedure will look    */
  495. /* to find the moves that are possible for white, returning the    */
  496. /* number. This is so that the white player is required to    */
  497. /* make 2 moves if a 2-move is possible. If the "computer" flag    */
  498. /* is true, the routine calls "w_eval" to find the best of the    */
  499. /* moves generated. This best move is formatted and returned in    */
  500. /* "line", in a format that can be understood by the command    */
  501. /* parser (just as if a user had entered it).            */
  502. /*                                */
  503. /* If all of that sounded familiar, it's because the remainder    */
  504. /* of these functions do the same thing as above, but with the    */
  505. /* direction (++ as opposed to --, < as opposed to >, etc.)    */
  506. /* reversed.                            */
  507. /*                                */
  508. /****************************************************************/
  509.  
  510. w_movegen( die_1, die_2, computer, biggest, line, echo )
  511.  
  512. int    die_1, die_2;
  513. int    computer, *biggest;
  514. char    line[];
  515. int    echo;
  516.  
  517.     {
  518.  
  519.     char    *format[ 5 ];
  520.     int    p[ 4 ], die[ 4 ], best_p[ 4 ], best_die[ 4 ], i, j;
  521.     int    temp, level, finished, copy, best, value, count;
  522.     int    test[ SIZE ][ 3 ];
  523.  
  524.     if ( ! computer )
  525.         *biggest = 0;
  526.     else
  527.         {
  528.         format[ 0 ] = "software bug?";
  529.         format[ 1 ] = "%d/%d";
  530.         format[ 2 ] = "%d/%d %d/%d";
  531.         format[ 3 ] = "%d/%d %d/%d %d/%d";
  532.         format[ 4 ] = "%d/%d %d/%d %d/%d %d/%d";
  533.         best = WORST;
  534.         }
  535.  
  536.     count = 0;
  537.     die[ 0 ] = die[ 2 ] = die_1;
  538.     die[ 1 ] = die[ 3 ] = die_2;
  539.  
  540.     /* Copy the board into the test area. The 2    */
  541.     /* is a temp. holding area for the opponents    */
  542.     /* men that are bumped off.            */
  543.  
  544.     movmem( board, test, BOARD_IN_BYTES );
  545.  
  546.     finished = 0;
  547.  
  548.     while ( finished < 2 )
  549.         {
  550.  
  551.         for( p[ 0 ] = W_BAR; p[ 0 ]; p[ 0 ]-- )
  552.             {
  553.  
  554.             if ( ! w_valid_move( test, p[ 0 ], die[ 0 ] ) )
  555.                 continue;
  556.  
  557.             level = 1;
  558.  
  559.             w_change( test, p[ 0 ], die[ 0 ], OFF );
  560.  
  561.             /* Now do the same thing within here,    */
  562.             /* using the other die as the value.    */
  563.     
  564.             for( p[ 1 ] = W_BAR; p[ 1 ]; p[ 1 ]-- )
  565.                 {
  566.     
  567.                 if ( ! w_valid_move( test, p[ 1 ], die[ 1 ] ) )
  568.                     continue;
  569.     
  570.                 w_change( test, p[ 1 ], die[ 1 ], OFF );
  571.  
  572.                 /* If we have doubles, we have yet another    */
  573.                 /* iteration of the two dice to go through here    */
  574.     
  575.                 if ( die[ 0 ] == die[ 1 ] )
  576.                     {
  577.     
  578.                     for( p[ 2 ] = W_BAR; p[ 2 ]; p[ 2 ]-- )
  579.                         {
  580.  
  581.                         if ( ! w_valid_move( test, p[ 2 ], die[ 2 ] ) )
  582.                             continue;
  583.     
  584.                         level = 3;
  585.     
  586.                         w_change( test, p[ 2 ], die[ 2 ], OFF );
  587.  
  588.                         /* Now do the same thing within here,    */
  589.                         /* using the other die as the value.    */
  590.     
  591.                         for( p[ 3 ] = W_BAR; p[ 3 ]; p[ 3 ]-- )
  592.                             {
  593.     
  594.                             if ( ! w_valid_move( test, p[ 3 ], die[ 3 ] ) )
  595.                                 continue;
  596.  
  597.                             w_change( test, p[ 3 ], die[ 3 ], OFF );
  598.     
  599.                             if ( bar_first( p, MIN( board[ W_BAR ][ WHITE ], 4 ) ) )
  600.                                 {
  601.  
  602.                                 level = 4;
  603.  
  604.                                 if ( ! computer )
  605.                                     {
  606.                                     *biggest = 4;
  607.                                     return;
  608.                                     }
  609.                                 else
  610.                                     {
  611.  
  612.                                     value = w_eval( test, count++ );
  613.                                     if ( value > best )
  614.                                         {
  615.  
  616.                                         best = value;
  617.                                         for( copy = 0; copy < 4; copy++ )
  618.                                             {
  619.                                             best_p[ copy ] = p[ copy ];
  620.                                             best_die[ copy ] = die[ copy ];
  621.                                             }
  622.  
  623.                                         }
  624.                                     }
  625.                                 }
  626.     
  627.                             w_change( test, p[ 3 ], die[ 3 ], ON );
  628.  
  629.                             } /* p[ 3 ] control loop */
  630.     
  631.                         if ( level == 3 )
  632.                             {
  633.  
  634.                             if ( ( *biggest <= 3                     ) &&
  635.                                  ( bar_first( p, MIN( board[ W_BAR ][ WHITE ], 3 ) ) ) )
  636.                                 {
  637.  
  638.                                 if ( ! computer )
  639.                                     *biggest = ( *biggest < 3 ) ? 3 : *biggest;
  640.                                 else
  641.                                     {
  642.  
  643.                                     value = w_eval( test, count++ );
  644.                                     if ( value > best )
  645.                                         {
  646.  
  647.                                         best = value;
  648.                                         for( copy = 0; copy < 3; copy++ )
  649.                                             {
  650.                                             best_p[ copy ] = p[ copy ];
  651.                                             best_die[ copy ] = die[ copy ];
  652.                                             }
  653.                                         }
  654.                                     }
  655.                                 }
  656.  
  657.                             } /* level 3 */
  658.     
  659.                         /* Put the pieces back where they were    */
  660.                         /* so that the next time through the    */
  661.                         /* loop we'll be using the originals.    */
  662.     
  663.                         w_change( test, p[ 2 ], die[ 2 ], ON );
  664.  
  665.                         } /* p[ 2 ] control loop */
  666.  
  667.                     /* If we had doubles but can only make    */
  668.                     /* two moves out of the possible 4...    */
  669.  
  670.                     if ( level == 1 )
  671.                         {
  672.  
  673.                         level = 2;
  674.  
  675.                         if ( ( *biggest <= 2                     ) &&
  676.                              ( bar_first( p, MIN( board[ W_BAR ][ WHITE ], 2 ) ) ) )
  677.                             {
  678.  
  679.                             if ( ! computer )
  680.                                 *biggest = ( *biggest < 2 ) ? 2 : *biggest;
  681.                             else
  682.                                 {
  683.  
  684.                                 value = w_eval( test, count++ );
  685.                                 if ( value > best )
  686.                                     {
  687.                                     best = value;
  688.                                     for( copy = 0; copy < 2; copy++ )
  689.                                         {
  690.                                         best_p[ copy ] = p[ copy ];
  691.                                         best_die[ copy ] = die[ copy ];
  692.                                         }
  693.                                     }
  694.                                 }
  695.                             }
  696.                         }
  697.  
  698.                     } /* Doubles handler */
  699.                 else
  700.                     {
  701.     
  702.                     /* If there were men on the original bar, we    */
  703.                     /* must remove them prior to making any other    */
  704.                     /* moves.                    */
  705.     
  706.                     if ( ( *biggest <= 2                     ) &&
  707.                          ( bar_first( p, MIN( board[ W_BAR ][ WHITE ], 2 ) ) ) )
  708.                         {
  709.  
  710.                         level = 2;
  711.  
  712.                         if ( ! computer )
  713.                             {
  714.                             *biggest = ( *biggest < 2 ) ? 2 : *biggest;
  715.                             return;
  716.                             }
  717.                         else
  718.                             {
  719.  
  720.                             value = w_eval( test, count++ );
  721.                             if ( value > best )
  722.                                 {
  723.  
  724.                                 best = value;
  725.                                 for( copy = 0; copy < 2; copy++ )
  726.                                     {
  727.                                     best_p[ copy ] = p[ copy ];
  728.                                     best_die[ copy ] = die[ copy ];
  729.                                     }
  730.                                 }
  731.                             }
  732.                         }
  733.     
  734.                     } /* not doubles */
  735.     
  736.                 w_change( test, p[ 1 ], die[ 1 ], ON );
  737.  
  738.                  } /* p[ 1 ] control loop */
  739.     
  740.             /* If "level" is still 1, we did not    */
  741.             /* find any use for the other die.    */
  742.     
  743.             if ( level == 1 )
  744.                 {
  745.  
  746.                 if ( ( *biggest <= 1                     ) &&
  747.                      ( bar_first( p, MIN( board[ W_BAR ][ WHITE ], 1 ) ) ) )
  748.                     {
  749.  
  750.                     if ( ! computer )
  751.                         *biggest = ( *biggest < 1 ) ? 1 : *biggest;
  752.                     else
  753.                         {
  754.  
  755.                         value = w_eval( test, count++ );
  756.                         if ( value > best )
  757.                             {
  758.                             best = value;
  759.                             best_p[ 0 ] = p[ 0 ];
  760.                             best_die[ 0 ] = die[ 0 ];
  761.                             }
  762.                         }
  763.                     }
  764.     
  765.                 } /* level 1 */
  766.     
  767.             /* Put the pieces back where they were    */
  768.             /* so that the next time through the    */
  769.             /* loop we'll be using the originals.    */
  770.     
  771.             w_change( test, p[ 0 ], die[ 0 ], ON );
  772.  
  773.             } /* p[ 0 ] control loop */
  774.  
  775.         /* If we had doubles, then we're done.    */
  776.         /* Otherwise rotate the dice (swap) and    */
  777.         /* do it all again, using, say 5,3 now    */
  778.         /* if the roll was 3,5.            */
  779.  
  780.         if ( die[ 0 ] == die[ 1 ] )
  781.             finished = 2;
  782.         else
  783.             {
  784.             temp = die[ 0 ];
  785.             die[ 0 ] = die[ 1 ];
  786.             die[ 1 ] = temp;
  787.             finished++;
  788.             }
  789.  
  790.         } /* while not finished yet */
  791.  
  792.     if ( computer )
  793.         {
  794.  
  795.         sprintf( line, format[ *biggest ],
  796.              best_p[ 0 ], best_die[ 0 ],
  797.              best_p[ 1 ], best_die[ 1 ],
  798.              best_p[ 2 ], best_die[ 2 ],
  799.              best_p[ 3 ], best_die[ 3 ] );
  800.  
  801.         write_at( 15, 65, "           ", TEXT_COLOR );
  802.  
  803.         } /* computer */
  804.  
  805.     } /* w_movegen */
  806.  
  807. /*P*/
  808. /****************************************************************/
  809. /*                                */
  810. /* w_exit_ok                            */
  811. /*                                */
  812. /* This returns true if it is ok for white to exit the board    */
  813. /* from this position.                        */
  814. /*                                */
  815. /****************************************************************/
  816.     
  817. w_exit_ok( test, psn, roll )
  818.  
  819. int    test[ SIZE ][ 3 ];
  820. int    psn, roll;
  821.  
  822.     {
  823.     
  824.     int    i;
  825.     
  826.     /* First off, if there is anyine not in the    */
  827.     /* inner table, you can not move them off.    */
  828.  
  829.     for( i = W_BAR; i > 6; i-- )
  830.         if ( test[ i ][ WHITE ] )
  831.             return( FALSE );
  832.  
  833.     /* Now, if the sum is EXACTLY 25, it is ok to    */
  834.     /* take them off regardless of the others.    */
  835.  
  836.     if ( ( psn - roll ) == W_HOME )
  837.         return( TRUE );
  838.  
  839.     /* Lastly, if we have, say, a 5 but there are    */
  840.     /* only men on 1, 2, and 3, ok to take off the    */
  841.     /* one at 3 only.                */
  842.  
  843.     for( i = psn + 1; i < 7; i++ )
  844.         if ( test[ i ][ WHITE ] )
  845.             return( FALSE );
  846.  
  847.     return( TRUE );
  848.  
  849.     } /* w_this_ok */
  850.  
  851. /*P*/
  852. /****************************************************************/
  853. /*                                */
  854. /* w_valid_move                            */
  855. /*                                */
  856. /* Same as above. If white can legally make this move, return a    */
  857. /* "true", else a "false".                    */
  858. /*                                */
  859. /****************************************************************/
  860.  
  861. w_valid_move( test, point, die )
  862.  
  863. int    test[ SIZE ][ 3 ], point, die;
  864.  
  865.     {
  866.  
  867.     if ( ! test[ point ][ WHITE ] )
  868.         return( FALSE );
  869.  
  870.     if ( ( point - die ) < 1 )
  871.         {
  872.         if ( ! w_exit_ok( test, point, die ) )
  873.             return( FALSE );
  874.         }
  875.     else
  876.         {
  877.         if ( test[ point - die ][ BLACK ] >= 2 )
  878.             return( FALSE );
  879.         }
  880.  
  881.     return( TRUE );
  882.  
  883.     } /* w_valid_move */
  884.  
  885. /*P*/
  886. /****************************************************************/
  887. /*                                */
  888. /* w_change                            */
  889. /*                                */
  890. /* Move a piece for white. If "on" is true, move it out. Else    */
  891. /* move it back where it was.                    */
  892. /*                                */
  893. /****************************************************************/
  894.  
  895. w_change( test, point, die, on )
  896.  
  897. int    test[ SIZE ][ 3 ], point, die, on;
  898.  
  899.     {
  900.  
  901.     if ( on )
  902.         {
  903.  
  904.         test[ point ][ WHITE ]++;
  905.         if ( point - die >= 1 )
  906.             {
  907.             test[ point - die ][ WHITE ]--;
  908.             if ( test[ point - die ][ 2 ] )
  909.                 {
  910.                 test[ point - die ][ BLACK ]++;
  911.                 test[ point - die ][ 2 ]--;
  912.                 }
  913.             }
  914.         }
  915.     else
  916.         {
  917.  
  918.         test[ point ][ WHITE ]--;
  919.         if ( point - die >= 1 )
  920.             {
  921.             test[ point - die ][ WHITE ]++;
  922.             if ( test[ point - die ][ BLACK ] == 1 )
  923.                 {
  924.                 test[ point - die ][ BLACK ]--;
  925.                 test[ point - die ][ 2 ]++;
  926.                 }
  927.             }
  928.         }
  929.  
  930.     } /* w_change */
  931.